# 标准库
import os
import traceback
import logging

# 第三方库
import asyncio
import importlib

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s"
)

module_mtime_map = {}


class CommandHandler:
    def __init__(self):
        self.handlers = {}
        self.help_map = {}

    def add_handler(self, keyword: str, func, help_short: str = None) -> None:
        self.handlers[keyword] = func
        if help_short:
            self.help_map[keyword] = help_short

    async def handle_message(self, message, interaction, reply, infos: dict) -> None:
        """统一入口：基于 dispatch 的命令分发 + 超时保护"""
        if not message:
            return

        msg = message.content.strip()

        # 使用 dispatch 分发表逻辑获取要执行的函数
        func = self.dispatch(msg)

        # 如果匹配到命令
        if func:
            await self.safe_invoke(func, message, infos, reply)
        else:
            # 没匹配到，兜底逻辑放这里
            pass

    def dispatch(self, msg) -> None:
        """
        分发表：
        根据消息内容匹配对应 handler。
        """
        # 普通注册命令
        for keyword, func in self.handlers.items():
            if msg.startswith(keyword) and keyword != "/":
                return func
        return None

    async def safe_invoke(self, func, message, infos, reply) -> None:
        """安全执行带超时保护的命令"""
        try:
            async with asyncio.timeout(30):  # 30 秒超时防护
                await func(message, infos)
        except asyncio.TimeoutError:
            logging.error(f"[CommandError] {message.content.strip()}: 超时")
            await reply(content=f"⏰ 指令执行超时：{message.content}")
        except Exception as e:
            tb_str = ''.join(traceback.format_exception(
                type(e), e, e.__traceback__))
            lineno = e.__traceback__.tb_lineno
            logging.error("发生未知错误:\n%s\n错误行号: %s", tb_str, lineno)
            logging.error(f"[CommandError] {message.content}: {e}")
            # await reply(content=f"⚠️ 执行指令出错：{str(e)[:100]}")


async def module_regist(flag, cmd_handler, lock, reply):
    global config, module_mtime_map
    
    modules_folder = os.path.join(os.path.dirname(__file__), "../../plugins")
    results = []  # 用于收集结果
    file_path = os.path.join(modules_folder, "_register.py")
   
    try:##新的，都在./plugins里
        mtime = os.path.getmtime(file_path)
        if flag == 1 or module_mtime_map.get("_register.py") != mtime:
            import plugins._register as register
            importlib.reload(register)
            module_mtime_map["_register.py"] = mtime
            results.append(f"register_module - √")
            logging.info("_register.py - √")
    except Exception as e:
        results.append(f"register_plugins - X")
        logging.exception(f"[ERROR] 异常: {e}")
        
    modules_folder = os.path.join(os.path.dirname(__file__), "../../modules")

    # 处理旧模块，./modules
    for module_name in os.listdir(modules_folder):
        if (
            module_name.endswith(".py")
            and not module_name.startswith("_")
        ):

            module_path = f"modules.{module_name[:-3]}"
            file_path = os.path.join(modules_folder, module_name)

            try:
                mtime = os.path.getmtime(file_path)

                # 初次 import
                if flag == 1:
                    module = importlib.import_module(module_path)
                    await module.register(cmd_handler, lock, reply)
                    module_mtime_map[module_name] = mtime

                # reload 变更的模块
                else:
                    if (
                        module_name not in module_mtime_map
                        or module_mtime_map[module_name] != mtime
                    ):
                        module = importlib.import_module(module_path)
                        importlib.reload(module)
                        ok = await module.register(cmd_handler, lock, reply)
                        results.append(f"{module_name} - {'√' if ok else 'X'}")
                        module_mtime_map[module_name] = mtime

            except Exception as e:
                error_msg = "".join(
                    traceback.format_exception_only(type(e), e)).strip()
                results.append(f"{module_name} - failed: {error_msg}")
                logging.exception(f"[ERROR] 模块 {module_path} 异常: {e}")

    return "\n".join(results) if flag == 0 else ""
